001 /*
002 * Copyright 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.library.info;
020
021 import java.util.Arrays;
022 import java.util.ArrayList;
023 import java.util.Properties;
024
025 import net.dpml.lang.Enum;
026
027 import net.dpml.transit.Artifact;
028
029 /**
030 * The ResourceDirective class describes an available resource.
031 *
032 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
033 * @version 1.1.0
034 */
035 public class ResourceDirective extends AbstractDirective
036 {
037 /**
038 * External resource constant identifier.
039 */
040 public static final Classifier EXTERNAL = Classifier.EXTERNAL;
041
042 /**
043 * Local resource constant identifier.
044 */
045 public static final Classifier LOCAL = Classifier.LOCAL;
046
047 /**
048 * Anonymous resource constant identifier.
049 */
050 public static final Classifier ANONYMOUS = Classifier.ANONYMOUS;
051
052 private final String m_scheme;
053 private final String m_name;
054 private final String m_version;
055 private final String m_basedir;
056 private final TypeDirective[] m_types;
057 private final DataDirective[] m_data;
058 private final DependencyDirective[] m_dependencies;
059 private final Classifier m_classifier;
060 private final FilterDirective[] m_filters;
061 private final InfoDirective m_info;
062
063 /**
064 * Creation of a new anonymous resource directive.
065 * @param scheme the schema name
066 * @param name the resource name
067 * @param version the resource version
068 * @param type the resource type
069 * @param properties suppliementary properties
070 * @return the resource directive
071 */
072 public static ResourceDirective createAnonymousResource(
073 String scheme, String name, String version, String type, Properties properties )
074 {
075 return new ResourceDirective( scheme, name, type, version, properties );
076 }
077
078 /**
079 * Creation of a new resource directive. If the resource name if composite
080 * then the resource directive will be a module directive instance that either
081 * encloses the resource or enclosed a resource containing the resource.
082 *
083 * @param name the resource name
084 * @param version the resource version
085 * @param classifier LOCAL or EXTERNAL classifier
086 * @param basedir the project basedir
087 * @param info info descriptor
088 * @param data types produced by the resource
089 * @param dependencies resource dependencies
090 * @param properties suppliementary properties
091 * @param filters project filters
092 * @return the immediate enclosing resource
093 */
094 public static ResourceDirective createResourceDirective(
095 String name, String version, Classifier classifier, String basedir,
096 InfoDirective info, DataDirective[] data,
097 DependencyDirective[] dependencies, Properties properties,
098 FilterDirective[] filters )
099 {
100 int n = name.indexOf( "/" );
101 if( n > -1 )
102 {
103 ResourceDirective resource = null;
104 String[] elements = name.split( "/", -1 );
105 for( int i = ( elements.length-1 ); i>-1; i-- )
106 {
107 String elem = elements[i];
108 if( i == ( elements.length-1 ) )
109 {
110 resource =
111 new ResourceDirective(
112 elem, version, classifier, basedir, info, data, dependencies,
113 properties, filters );
114 }
115 else
116 {
117 resource =
118 new ModuleDirective(
119 elem, null, Classifier.EXTERNAL, null, null,
120 new DataDirective[0], new DependencyDirective[0],
121 new ResourceDirective[]{resource}, null, null );
122 }
123 }
124 return resource;
125 }
126 else
127 {
128 return new ResourceDirective(
129 name, version, classifier, basedir, info, data,
130 dependencies, properties, filters );
131 }
132 }
133
134 /**
135 * Creation of a new annonomous resource directive.
136 * @param scheme the resource schema (artifact or link)
137 * @param name the resource name
138 * @param version the resource version
139 * @param properties suppliementary properties
140 */
141 private ResourceDirective(
142 String scheme, String name, String type, String version, Properties properties )
143 {
144 super( properties );
145
146 if( null == name )
147 {
148 throw new NullPointerException( "name" );
149 }
150
151 m_name = name;
152 m_types = new TypeDirective[]{new TypeDirective( type )};
153 m_data = m_types;
154 m_dependencies = new DependencyDirective[0];
155 m_classifier = Classifier.ANONYMOUS;
156 m_version = version;
157 m_basedir = ".";
158 m_info = new InfoDirective( null, null );
159 m_filters = new FilterDirective[0];
160 m_scheme = scheme;
161 }
162
163 /**
164 * Creation of a new resource directive.
165 * @param name the resource name
166 * @param version the resource version
167 * @param classifier LOCAL or EXTERNAL classifier
168 * @param basedir the project basedir
169 * @param info info descriptor
170 * @param data type production data
171 * @param dependencies resource dependencies
172 * @param properties suppliementary properties
173 * @param filters suppliementary filters
174 */
175 ResourceDirective(
176 String name, String version, Classifier classifier, String basedir,
177 InfoDirective info, DataDirective[] data,
178 DependencyDirective[] dependencies, Properties properties,
179 FilterDirective[] filters )
180 {
181 super( properties );
182
183 if( null == name )
184 {
185 throw new NullPointerException( "name" );
186 }
187 if( null == data )
188 {
189 throw new NullPointerException( "data" );
190 }
191 if( null == dependencies )
192 {
193 throw new NullPointerException( "dependencies" );
194 }
195 if( null == classifier )
196 {
197 throw new NullPointerException( "classifier" );
198 }
199
200 m_name = name;
201 m_version = version;
202 m_basedir = basedir;
203 m_classifier = classifier;
204 m_scheme = Artifact.ARTIFACT;
205
206 if( null == info )
207 {
208 m_info = new InfoDirective( null, null );
209 }
210 else
211 {
212 m_info = info;
213 }
214
215 m_dependencies = dependencies;
216
217 if( null == filters )
218 {
219 m_filters = new FilterDirective[0];
220 }
221 else
222 {
223 m_filters = filters;
224 }
225
226 ArrayList list = new ArrayList();
227 for( int i=0; i<data.length; i++ )
228 {
229 DataDirective directive = data[i];
230 if( directive instanceof TypeDirective )
231 {
232 list.add( directive );
233 }
234 }
235 m_types = (TypeDirective[]) list.toArray( new TypeDirective[0] );
236 m_data = data;
237 }
238
239 /**
240 * Return the resource name.
241 * @return the name
242 */
243 public String getName()
244 {
245 return m_name;
246 }
247
248 /**
249 * Return the resource version.
250 * @return the version
251 */
252 public String getVersion()
253 {
254 return m_version;
255 }
256
257 /**
258 * Return the resource basedir.
259 * @return the basedir
260 */
261 public String getBasedir()
262 {
263 return m_basedir;
264 }
265
266 /**
267 * Return the info descriptor.
268 * @return the info descriptor
269 */
270 public InfoDirective getInfoDirective()
271 {
272 return m_info;
273 }
274
275 /**
276 * Return the resource classifier.
277 * @return the classifier (LOCAL, EXTERNAL or ANONYMOUS)
278 */
279 public Classifier getClassifier()
280 {
281 return m_classifier;
282 }
283
284 /**
285 * Return true if this represents a local project.
286 * @return true if local
287 */
288 public boolean isLocal()
289 {
290 return LOCAL.equals( m_classifier );
291 }
292
293 /**
294 * Return true if this represents a anonymous resource.
295 * @return true if anonymous
296 */
297 public boolean isAnonymous()
298 {
299 return ANONYMOUS.equals( m_classifier );
300 }
301
302 /**
303 * Return the scheme to use when declaring the published artifact (used
304 * in conjunction with anonymous resources.
305 * @return the scheme
306 */
307 public String getScheme()
308 {
309 return m_scheme;
310 }
311
312 /**
313 * Return an array of types representing artifacts associated
314 * with the resource.
315 * @return the type directives
316 */
317 public TypeDirective[] getTypeDirectives()
318 {
319 return m_types;
320 }
321
322 /**
323 * Return an array of supplimentary filter directives.
324 * @return the filter directives
325 */
326 public FilterDirective[] getFilterDirectives()
327 {
328 return m_filters;
329 }
330
331 /**
332 * Return an array of supporting production data directives
333 * (including all produced types).
334 * @return the data directives
335 */
336 public DataDirective[] getDataDirectives()
337 {
338 return m_data;
339 }
340
341 /**
342 * Return an named type.
343 * @param name the type name
344 * @return the type directives
345 * @exception TypeUnknownException if the type name if not recornized within
346 * the scope of the resource
347 */
348 public TypeDirective getTypeDirective( String name ) throws TypeUnknownException
349 {
350 for( int i=0; i<m_types.length; i++ )
351 {
352 TypeDirective type = m_types[i];
353 if( name.equals( type.getID() ) )
354 {
355 return type;
356 }
357 }
358 throw new TypeUnknownException( name );
359 }
360
361 /**
362 * Return an array of dependency directives.
363 * @return the dependency directive array
364 */
365 public DependencyDirective[] getDependencyDirectives()
366 {
367 return m_dependencies;
368 }
369
370 /**
371 * Return an dependency directive matching a supplied scope.
372 * @param scope the scope
373 * @return the dependency directive matching the supplied scope
374 */
375 public DependencyDirective getDependencyDirective( Scope scope )
376 {
377 for( int i=0; i<m_dependencies.length; i++ )
378 {
379 DependencyDirective directive = m_dependencies[i];
380 if( scope.equals( directive.getScope() ) )
381 {
382 return directive;
383 }
384 }
385 return new DependencyDirective( scope, new IncludeDirective[0] );
386 }
387
388 /**
389 * Compare this object with another for equality.
390 * @param other the other object
391 * @return true if equal
392 */
393 public boolean equals( Object other )
394 {
395 if( super.equals( other ) && ( other instanceof ResourceDirective ) )
396 {
397 ResourceDirective object = (ResourceDirective) other;
398 if( !equals( m_name, object.m_name ) )
399 {
400 return false;
401 }
402 else if( !equals( m_scheme, object.m_scheme ) )
403 {
404 return false;
405 }
406 else if( !equals( m_version, object.m_version ) )
407 {
408 return false;
409 }
410 else if( !equals( m_basedir, object.m_basedir ) )
411 {
412 return false;
413 }
414 else if( !equals( m_info, object.m_info ) )
415 {
416 return false;
417 }
418 else if( !Arrays.equals( m_data, object.m_data ) )
419 {
420 return false;
421 }
422 else
423 {
424 return Arrays.equals( m_dependencies, object.m_dependencies );
425 }
426 }
427 else
428 {
429 return false;
430 }
431 }
432
433 /**
434 * Compute the hash value.
435 * @return the hashcode value
436 */
437 public int hashCode()
438 {
439 int hash = super.hashCode();
440 hash ^= super.hashValue( m_name );
441 hash ^= super.hashValue( m_scheme );
442 hash ^= super.hashValue( m_version );
443 hash ^= super.hashValue( m_basedir );
444 hash ^= super.hashValue( m_info );
445 hash ^= super.hashArray( m_data );
446 hash ^= super.hashArray( m_dependencies );
447 hash ^= super.hashArray( m_filters );
448 return hash;
449 }
450
451 /**
452 * Resource classifier enumeration.
453 * @author <a href="mailto:dev-dpml@lists.ibiblio.org">The Digital Product Meta Library</a>
454 */
455 public static final class Classifier extends Enum
456 {
457 static final long serialVersionUID = 1L;
458
459 /**
460 * Anonymous resources.
461 */
462 public static final Classifier ANONYMOUS = new Classifier( "anonymous" );
463
464 /**
465 * External resource.
466 */
467 public static final Classifier EXTERNAL = new Classifier( "external" );
468
469 /**
470 * Local resources.
471 */
472 public static final Classifier LOCAL = new Classifier( "local" );
473
474 /**
475 * Internal constructor.
476 * @param label the enumeration label.
477 */
478 private Classifier( String label )
479 {
480 super( label );
481 }
482
483 /**
484 * Create a classified matching the supplied name.
485 * @param value the classifier name
486 * @return the classifier
487 * @exception IllegalArgumentException if the supplied value is not recognized
488 */
489 public static Classifier parse( String value ) throws IllegalArgumentException
490 {
491 if( value.equalsIgnoreCase( "external" ) )
492 {
493 return EXTERNAL;
494 }
495 else if( value.equalsIgnoreCase( "local" ) )
496 {
497 return LOCAL;
498 }
499 else if( value.equalsIgnoreCase( "anonymous" ) )
500 {
501 return ANONYMOUS;
502 }
503 else
504 {
505 final String error =
506 "Unrecognized module classifier argument [" + value + "]";
507 throw new IllegalArgumentException( error );
508 }
509 }
510 }
511 }